package com.zdft.promotion.sso.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zdft.promotion.sso.vo.AuthenticationVO;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

/**
 * Created by Administrator on 2019/3/25.
 */
public class AuthenticationLoadFilter implements Filter {
    private static final Logger log = LoggerFactory.getLogger(AuthenticationLoadFilter.class);

    @Value("${url.sso.authentication}")
    private String authenticationUrl;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        AuthenticationVO vo = getSession(servletRequest, servletResponse);

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String origin = request.getHeader("Origin");

        ((HttpServletResponse) servletResponse).setHeader("Access-Control-Allow-Origin", origin);
        ((HttpServletResponse) servletResponse).setHeader("access-control-allow-credentials", "true");
        ((HttpServletResponse) servletResponse).setHeader("Access-Control-Allow-Headers", "Content-Type");
        ((HttpServletResponse) servletResponse)
                .setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,PATCH,OPTIONS");

        if (null == vo) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        AuthenticationUtil.set(vo);
        try {
            filterChain.doFilter(servletRequest, servletResponse);
        } finally {
            AuthenticationUtil.clear();
        }
    }

    @Override
    public void destroy() {
    }

    private AuthenticationVO getSession(ServletRequest request, ServletResponse response) throws IOException {
        String sessionToken = getToken(request);
        if (null == sessionToken) {
            return null;
        }
        InputStream stream = new URL(authenticationUrl + "?_session_token=" + sessionToken).openStream();
        StringBuilder builder = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(stream, "utf-8"))) {
            String str = br.readLine();
            while (str != null) {
                builder.append(str).append('\n');
                str = br.readLine();
            }
        }
        JSONObject object = JSON.parseObject(builder.toString());
        log.debug("Authenticate:{}.", object);
        if ("0".equals(object.getString("code"))) {
            return object.getObject("object", AuthenticationVO.class);
        }
        return null;
    }

    /**
     * 获取session token
     * 兼容vue无法携带cookie请求服务端，优先从请求参数列表获取
     *
     * @param request request
     * @return tk
     */
    private String getToken(ServletRequest request) {
        HttpServletRequest req = (HttpServletRequest) request;
        String sessionToken = req.getParameter("_session_token");
        if (StringUtils.isNotEmpty(sessionToken)) {
            return sessionToken;
        }

        Cookie[] cookies = req.getCookies();
        if (ArrayUtils.isEmpty(cookies)) {
            return null;
        }
        for (Cookie cookie : cookies) {
            if ("sessionToken".equals(cookie.getName())) {
                return cookie.getValue();
            }
        }
        return null;
    }
}
